/**
 * 通过混入 了解 构造函数类型。
 */

/**
 * 1. 混入
 * 方法： 扩展运算符、Object.assign、原型、闭包高阶组件混入
 */
const canEat = {
  eat: function () {
    console.log("eating");
  },
};
const canWalk = {
  walk: function () {
    console.log("walking");
  },
};
class Person {
  constructor(public name: string) {
    this.name = name;
  }
}
// const person = { ...canEat, ...canWalk }; // 扩展运算符 混入
// const person = Object.assign({}, canEat, canWalk); // Object.assign 混入
const person = Object.assign(Person.prototype, canEat, canWalk); // 原型方式 混入
// person.eat();
// person.walk();
/**
 * 闭包实现混入
 * @param Class
 * @returns
 */
function withEating(Class) {
  return class extends Class {
    eat() {
      console.log("eating");
    }
  };
}
function withWalking(Class) {
  return class extends Class {
    walk() {
      console.log("walking");
    }
  };
}

const EatingWalkingPerson = withWalking(withEating(Person));
const person2 = new EatingWalkingPerson();
// person2.eat();
// person2.walk();

/**
 * 基础类
 */
class MyClass {
  constructor(public name: string) {}
}
class YourClass {
  constructor(public age: number) {}
}
type ClassConstructor = new (...args: any[]) => any; // 构造函数类型

type Constructor<T> = new (...args: any[]) => T;
/**
 * 闭包实现混入
 * 通过构造函数 Constructor<MyClass> 类型限定Base的类型
 * @param Base
 * @returns
 */
function Timestamped<TBase extends Constructor<MyClass>>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}
function Printable<TBase extends Constructor<MyClass>>(Base:   TBase) {
  return class extends Base {
    print() {
      console.log(this);
    }
  };
}
const TimeAndPrintMyClass = Printable(Timestamped(MyClass));
const example = new TimeAndPrintMyClass("test");
console.log(example.name);
example.print();
console.log(example.timestamp);
console.log(example);
